﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Core;
using Core.LockStep;
using Message;

internal class UdpConnectSystem : EntitySystem, IAwake
{
    ISession session;

    // 预先发送5帧
    public int predictionTick = 5;
    // 发送延迟
    public int haltRtt;

    public int playerId;
    public int netDelayTime;

    private bool isPlay;

    public void Awake()
    {
        Subscribe<OnConnectTcpServerCompleted>(OnConnectTcpServerCompleted);
        Subscribe<OnDisconnectTcpServerCompleted>(OnDisconnectTcpServerCompleted);
        Subscribe<BattleCommandServerPush>(BattleCommandServerPush);
        Subscribe<BattleCommandPlayerPushTime>(BattleCommandPlayerPushTime);
        Subscribe<BattleStartPush>(BattleStartPush);
        Subscribe<SetPlayerId>(SetPlayerId);
        Subscribe<SendFrameData>(SendFrameData);
        Subscribe<PauseLockStep>(PauseLockStep);
    }

    private void PauseLockStep(ref PauseLockStep data)
    {
        isPlay = false;
    }

    private void BattleStartPush(ref BattleStartPush data)
    {
        isPlay = true;

        var battleInfo = new BattleInfoData();
        battleInfo.playerId = playerId;
        battleInfo.playerCount = data.playerCount;
        battleInfo.playerIds = data.playerIds;

        new StartLockStep(battleInfo, netDelayTime, true, false).Publish();
    }

    private void SendFrameData(ref SendFrameData data)
    {
        if (!isPlay)
            return;

        if (session == null)
            return;

        var push = new BattleCommandPlayerPush();
        push.tick = data.frameIndex;

        if (data.frameDataStream != null)
        {
            push.data = new byte[data.frameDataStream.Length];
            Array.Copy(data.frameDataStream.GetBuffer(), 0, push.data, 0, data.frameDataStream.Length);
        }

        session.SendMessage(push);
    }

    private void SetPlayerId(ref SetPlayerId data)
    {
        playerId = data.playerId;
    }

    private void OnDisconnectTcpServerCompleted(ref OnDisconnectTcpServerCompleted data)
    {
        isPlay = false;

        session = null;
        Log.Info($"链接断开，SessionID: {data.session.SessionID}");
    }

    private void BattleCommandServerPush(ref BattleCommandServerPush data)
    {
        if (!isPlay)
            return;

        //Log.Info($"接收命令 BattleCommandPush:{data.tick}");
        new ReceiveFrameData(data.datas, data.tick).Publish();
    }

    private void BattleCommandPlayerPushTime(ref BattleCommandPlayerPushTime data)
    {
        if (!isPlay)
            return;

        new ReceiveFrameTime(data.tick, data.serverFrameIndex, data.currentSumTime).Publish();
    }

    private void OnConnectTcpServerCompleted(ref OnConnectTcpServerCompleted data)
    {
        Log.Info($"client connect udp:{data.isConnect}");
        session = data.session;
        SendReady();
    }

    private async void SendReady()
    {
        var userId = (uint)playerId;

        var time = DateTime.Now;
        // 发送准备请求
        var response = await session.RpcMessage<BattleReadyResponse>(new BattleReadyRequest() { userId = userId });
        session.Register(userId);

        netDelayTime = (int)((DateTime.Now - time).TotalMilliseconds / 2);
    }
}